package classes
{
	import classes.utils.Configuration;
	import classes.utils.Utility;
	
	import flash.filesystem.File;
	
	import mx.collections.ArrayCollection;
	
	[Bindable]
	public class User implements WritableObject
	{
	
		private var _userName:String;
		public var password:String;
		public var securityQuestion:String;
		public var securityQuestionAnswer:String;
		public var dataDirectory:String;
		public var backupDirectory:String;
		public var encryptionKey:String;	
		/*public var accountHead:Account;
		public var accountTail:Account;
		public var accountTraverse:Account;*/
		public var accounts:ArrayCollection;
		public var categories:ArrayCollection;
		public var recipients:ArrayCollection;
		public var budgetCategories:ArrayCollection;
		
		
		public var totalWorth:Number = 0;		
		
		public function User()
		{
			super();
			this.accounts = new ArrayCollection();
			this.categories = new ArrayCollection();	//TODO: GET DEFAULT CATEGORIES
			this.recipients = new ArrayCollection();
			this.budgetCategories = new ArrayCollection();
		}		
		
		//TODO: change raw:String to raw:XML...or not...?
		//	we could keep it as a string here, and pass XMLs down
		//  That way, we can pass the string straight from the file reader
		public function parseUserString(raw:String):void{
			var xml:XML = new XML(raw);
			
			this.userName = xml.@userName;
			this.password = xml.@password;
			
			if(this.userName == "" || this.password == "")
				Utility.getInstance().showAlert("Error Loading User: Empty Data", "Parse Error");
			
			this.dataDirectory = xml.@dataDirectory;
			this.backupDirectory = xml.@backupDirectory;
			
			this.encryptionKey = xml.@encryptionKey;
			
			this.securityQuestion = xml.@securityQuestion;
			this.securityQuestionAnswer = xml.@securityQuestionAnswer;
			
			var rawData:XMLList = xml.children();
			var rawAccounts:XMLList = new XMLList();
			var rawCategories:XMLList = new XMLList();
			var rawRecipients:XMLList = new XMLList();
			var rawBudgetCategories:XMLList = new XMLList();
			
			var i:int = 0;
			for(; i < rawData.length(); i++){
				var item:XML = rawData[i] as XML;
				
				switch(item.localName().toUpperCase()){
					case "ACCOUNT":			rawAccounts += item; break;
					case "CATEGORY":		rawCategories += item; break;
					case "RECIPIENT":		rawRecipients += item; break;
					case "BUDGET":			rawBudgetCategories += item; break;
					case "CONFIGURATION":	Configuration.loadUserConfiguration(item) break;
					
					default:			
						trace("ERROR PARSING USER DATA: " + item); 
						Utility.getInstance().showAlert("Error Parsing User Data", "Parse Error");
				}
			}
			
			var x:int;
			var dupe:Boolean = false;
			
			this.categories = new ArrayCollection();
			i = 0;
			for(; i < rawCategories.length(); i++){
				dupe = false;
				var rawCat:XML = rawCategories[i];
				var newCategory:Category = new Category();
				newCategory.parseCategoryString(rawCat);
				
				for(x = 0; x < this.categories.length; x++){
					if(this.categories.getItemAt(x).name == newCategory.name){
						dupe = true;
						break;
					}
				}
				
				if(!dupe){
					this.categories.addItem(newCategory);
				}
			}
			
			this.recipients = new ArrayCollection();
			i = 0;
			for(; i < rawRecipients.length(); i++){
				dupe = false;
				var rawRecip:XML = rawRecipients[i];
				var newRecip:Recipient = new Recipient();
				newRecip.parseRecipientString(rawRecip);
				
				for(x = 0; x < this.recipients.length; x++){
					if(this.recipients.getItemAt(x).name == newRecip.name){
						dupe = true;
						break;
					}
				}
				
				if(!dupe){
					this.recipients.addItem(newRecip);
				}
			}
			
			//Model categories/recipients should be set;
			if(this.categories.length == 0)
				this.categories = TreasuryModel.getInstance().currentCategories;
			else
				TreasuryModel.getInstance().currentCategories = this.categories;
			
			TreasuryModel.getInstance().currentRecipients = this.recipients;
			
			//NOTE: accounts should not have dupes, but don't check here
			//	so there is no loss of data
			this.accounts = new ArrayCollection();
			i = 0;
			for(; i < rawAccounts.length(); i++){
				var rawAccount:XML = rawAccounts[i];
				var newAccount:Account = new Account();
				newAccount.parseAccountString(rawAccount);
				this.accounts.addItem(newAccount);
			}
			
			// this is the part that reads in the Budget Category stuff. 
			this.budgetCategories = new ArrayCollection();
			i = 0;
			for(; i < rawBudgetCategories.length(); i++){
				var rawBudgetCategory:XML = rawBudgetCategories[i];
				var newBudgetCategory:Budget = new Budget();
				newBudgetCategory.parseBudgetString(rawBudgetCategory);
				this.budgetCategories.addItem(newBudgetCategory);
			}
			
		}
		
		public function getSimpleUserString():String{
			return "<User userName=\"" + this.userName + "\" password=\"" + this.password +  
							"\" securityQuestion=\"" + this.securityQuestion + 
							"\" securityQuestionAnswer=\"" + this.securityQuestionAnswer + 
							"\" dataDirectory=\"" + this.dataDirectory +
							"\" backupDirectory=\""+ this.backupDirectory + 
							"\" encryptionKey=\"" + this.encryptionKey +  "\"/>";
		}

		public function toWritableString():String
		{
			// in this function add all the attributes of the class in the xml format.
			// for the array attributes, iterate through the list and add all the objects in the list. 
			var s:String = "<User userName=\"" + this.userName + "\" password=\"" + this.password +  
							"\" securityQuestion=\"" + this.securityQuestion + 
							"\" securityQuestionAnswer=\"" + this.securityQuestionAnswer + 
							"\" dataDirectory=\"" + this.dataDirectory +
							"\" backupDirectory=\""+ this.backupDirectory + 
							"\" encryptionKey=\"" + this.encryptionKey +  "\" >";
			
			var i:int = 0;
			//for loop iterating through accounts
			for(; i < this.accounts.length; i++){
				var account:Account = this.accounts.getItemAt(i) as Account;
				s += account.toWritableString();
			}
			
			//loop through Categories and Recipients
			i = 0;
			for(; i < this.categories.length; i++){
				var cat:Category = this.categories.getItemAt(i) as Category;
				if(cat.name != "")
					s += cat.toWritableString();
			}
			
			i = 0;
			for(; i < this.recipients.length; i++){
				var r:Recipient = this.recipients.getItemAt(i) as Recipient;
				s += r.toWritableString();
			}
			
		// loop through budgetCategories.
			i = 0;
			for(; i <this.budgetCategories.length; i++){
				var budCat:Budget = this.budgetCategories.getItemAt(i) as Budget;
				s += budCat.toWritableString();
			}
			
			s += "</User>";
			
			return s;
		}
		public function addBudgetCategory(budget:Budget):void{
				this.budgetCategories.addItem(budget);
		}
		public function deleteBudgetCategory(budget:Budget):void{
			var found:Boolean = false;
			var i:int = 0;
			for(; i< this.budgetCategories.length; i++){
				if(this.budgetCategories.getItemAt(i) == budget){
					this.budgetCategories.removeItemAt(i);
					found = true;
					break;
				} 
			}
			
			//TreasuryModel.getInstance().recalculateUserData();*/
		}
		public function createNewAccount(account:Account):Account
		{
			/*newAccount = new Account();
			newAccount.userName = accountName;
			if(accountHead == null){
				accountHead = newAccount;
				accountTail = newAccount;
			}
			else if (accountHead != null){
				accountTraverse = newAccount;
				accountTraverse.accountPrev = accountTail;
				accountTail.accountNext = accountTraverse;
				accountTail = accountTail.accountNext;
			}
			
			
			return null;*/
			
			for(var i:int = 0; i < this.accounts.length; i++){
				if(this.accounts.getItemAt(i).accountName == account.accountName){
					//cannot create account; duplicate name
					Utility.getInstance().showAlert(
						"Cannot create account: account with name '" 
						+ account.accountName + "' already exists",
						"Account Creation Error"
					);
					return null;
				}
			}
			
			//account.transactions = new ArrayCollection();
			
			this.accounts.addItem(account);
			TreasuryModel.getInstance().activeAccount = account;
			
			return account;
		}
		public function deleteAccount(account:Account):void
		{
			/*if(accountHead != null){
				accountTraverse = accountHead;
				while(accountTraverse != null){
					if(accountTraverse.accountName == account.accountName){
						if(accountTraverse.accountNext != null && accountTraverse.accountPrev != null){
							accountTraverse.accountPrev.accountNext = accountTraverse.accountNext;
							accountTraverse.accountNext.accountPrev = accountTraverse.accountPrev;
						}
						else if(accountTraverse.accountNext != null && accountTraverse.accountPrev == null){
							accountHead = accountHead.accountNext;
							accountHead.accountPrev = null;
						}
						else if(accountTraverse.accountNext == null && accountTraverse.accountPrev != null){
							accountTail = accountTail.accountPrev;
							accountTail.accountNext = null;
						}
						else{
							accountTail = null;
							accountHead = null;
						}
					}
					accountTraverse = accountTraverse.accountNext;
				}
				return;
			}*/
			
			for(var i:int = 0; i < this.accounts.length; i++){
				if(this.accounts.getItemAt(i) == account){
					this.accounts.removeItemAt(i);
				}
			}
		}
		public function requestPassword(securityAnswer:String):String
		{
		//Edit output of this method into dialog box
			if(securityAnswer == securityQuestionAnswer){
				return password;
			}
			else{

				return "You have entered the wrong answer.";

				Utility.getInstance().showAlert("Incorrect answer to question.", "Incorrect Answer");
				return "";

			}
		}
		
		public function calculateTotalWorth():Number{
			this.totalWorth = 0;
			
			for(var i:int = 0; i < this.accounts.length; i++){
				this.totalWorth += this.accounts.getItemAt(i).calculateBalance();
			}
			
			return this.totalWorth;
			
		}
		
		public function get userName():String{
			return this._userName;
		}
	
		public function set userName(name:String){
			this._userName = name;
			this.dataDirectory = File.documentsDirectory.nativePath + "\\Treasury\\data\\" + this.userName + ".tsf";
		}
		
		
	}
}